﻿using System;
using System.Globalization;
using System.Text.RegularExpressions;

namespace OccupierArchiver.Helpers
{
    internal static class FormatFactory
    {
        public static string MSSQLEscape(string str)
        {
            return Regex.Replace(str, @"[\x00'\b\n\r\t\cZ\\_]",
                delegate(Match match)
                {
                    string v = match.Value;
                    switch (v)
                    {
                        case "\'":            // QUOTE character
                            return "\'\'";
                        case "\x00":            // ASCII NUL (0x00) character
                            return "\\0";
                        case "\b":              // BACKSPACE character
                            return "\\b";
                        case "\n":              // NEWLINE (linefeed) character
                            return "\\n";
                        case "\r":              // CARRIAGE RETURN character
                            return "\\r";
                        case "\t":              // TAB
                            return "\\t";
                        case "\u001A":          // Ctrl-Z
                            return "\\Z";
                        default:
                            return "\\" + v;
                    }
                });
        }

        public static string MySQLEscape(string str)
        {
            return Regex.Replace(str, @"[\x00'""\b\n\r\t\cZ\\%_]",
                delegate(Match match)
                {
                    string v = match.Value;
                    switch (v)
                    {
                        case "\x00":            // ASCII NUL (0x00) character
                            return "\\0";
                        case "\b":              // BACKSPACE character
                            return "\\b";
                        case "\n":              // NEWLINE (linefeed) character
                            return "\\n";
                        case "\r":              // CARRIAGE RETURN character
                            return "\\r";
                        case "\t":              // TAB
                            return "\\t";
                        case "\u001A":          // Ctrl-Z
                            return "\\Z";
                        default:
                            return "\\" + v;
                    }
                });
        }

        public static string GetCurrencyCode(string strIn)
        {
            // Japanese Yen, Chinese Yuan
            string[] jpy = { "¥", "￥", "・･", "円", "圓", "jpy", "yen" };
            foreach (var item in jpy)
            {
                if (strIn.Contains(item))
                {
                    return "¥";
                }
            }
            // U.S. Dollar, Australian Dollar,...
            string[] usd = { "$", "＄", "usd" };
            foreach (var item in usd)
            {
                if (strIn.Contains(item))
                {
                    return "$";
                }
            }
            return "";
        }

        /// <summary>
        ///     Replace invalid characters and keep only numeric characters in a string.
        /// </summary>
        /// <param name="strIn">The input string needs to clean.</param>
        /// <returns>The cleaned string, with invalid characters removed.</returns>
        public static string CleanInput(string strIn)
        {
            return Regex.Replace(strIn, @"[^\d\.,]", "");
        }

        /// <summary>
        ///     <para>Convert a number in byte unit to another unit.</para>
        ///     <para>See more at: http://loliraki.tk/2011/10/16/php-convert-bytes-1 </para>
        /// </summary>
        /// <param name="bytes">File size in byte unit.</param>
        /// <param name="offset">The target unit you want to convert <paramref name="bytes" /> to.</param>
        /// <returns><paramref name="bytes" /> converted to a possible or defined unit if success.</returns>
        /// <exception cref="System.ArgumentOutOfRangeException"></exception>
        public static string SizeFormat(long bytes, int offset = -1)
        {
            string[] units = { "B", "KB", "MB", "GB", "TB", "PB", "EB", "ZB", "YB" };
            // int c = 0;
            if (offset < 0)
            {
                object[] r = { bytes, units[0] };
                for (int k = 0; k < units.Length; k++)
                {
                    if ((bytes / Math.Pow(1024, k)) >= 1)
                    {
                        r[0] = bytes / Math.Pow(1024, k);
                        r[1] = units[k];
                        // c++;
                    }
                }
                return String.Format("{0:N} {1}", r[0], r[1]);
            }
            if (offset < 9)
            {
                return (bytes / Math.Pow(1024, offset)).ToString("N") + " " + units[offset];
            }
            throw new ArgumentOutOfRangeException("offset");
        }

        /// <summary>
        ///     <para>Convert a string representing a size of a file to byte unit.</para>
        ///     <para>See more at: http://loliraki.tk/2011/10/18/php-convert-bytes-2 </para>
        /// </summary>
        /// <param name="value">File size in B, KB, MB, GB,...</param>
        /// <returns><paramref name="value" /> converted to an int64.</returns>
        public static long SizeGet(string value)
        {
            long result;
            double res;

            if (Int64.TryParse(value, out result))
            {
                return result;
            }
            value = value.Trim().ToLower().Replace("b", "");
            char last = value[value.Length - 1];
            value = CleanInput(value);
            switch (last)
            {
                case 'y':
                    res = Double.Parse(value) * 1024 * 1024 * 1024 * 1024 * 1024 * 1024 * 1024 * 1024;
                    break;
                case 'z':
                    res = Double.Parse(value) * 1024 * 1024 * 1024 * 1024 * 1024 * 1024 * 1024;
                    break;
                case 'e':
                    res = Double.Parse(value) * 1024 * 1024 * 1024 * 1024 * 1024 * 1024;
                    break;
                case 'p':
                    res = Double.Parse(value) * 1024 * 1024 * 1024 * 1024 * 1024;
                    break;
                case 't':
                    res = Double.Parse(value) * 1024 * 1024 * 1024 * 1024;
                    break;
                case 'g':
                    res = Double.Parse(value) * 1024 * 1024 * 1024;
                    break;
                case 'm':
                    res = Double.Parse(value) * 1024 * 1024;
                    break;
                case 'k':
                    res = Double.Parse(value) * 1024;
                    break;
                default:
                    res = Double.Parse(value);
                    break;
            }
            result = Int64.Parse(Math.Round(res, 0).ToString(CultureInfo.InvariantCulture));
            return result;
        }
    }
}
